import * as mysql from 'mysql';
import crypto from './crypto';



function nop(a?, b?, c?, d?, e?, f?, g?){

}



export default class Db{
    
    static pool: mysql.IPool;

    static init(config: mysql.IPoolConfig){
        this.pool = mysql.createPool({
            host: config.host,
            user: config.user,
            password: config.password,
            database: config.database,
            port: config.port
        });
    }

    static query(sql: string, callback:(err, rows:ret[], fields) => void){
        
        this.pool.getConnection(function(err, conn){
            if(err){
                callback(err, null, null);
            }
            else{
                conn.query(sql, function(qerr, vals:any[], fields){
                    //释放连接
                    conn.release();
                    
                    callback(qerr, vals, fields);
                });
            }
        });
    }

    static get_user_data(account?, callback:(data:ret)=>void = nop){

        if(account == null){
            callback(null);
            return;
        }

        const sql = 'SELECT userid,account,name,lv,coins,gems,roomid FROM t_users WHERE account = "' + account + '"';
        this.query(sql, function(err, rows: any[], fields){
            if(err){
                callback(null);
                throw err;
            }
            if(rows.length == 0){
                callback(null);
                return;
            }
            rows[0].name = crypto.fromBase64(rows[0].name);
            callback(rows[0]);
        });
    }

    static get_room_id_of_user(userid, callback: (data: ret) => void = nop){
        const sql = 'SELECT roomid FROM t_users WHERE userid = "' + userid + '"';
        this.query(sql, function(err, rows: ret[], fields){
            if(err){
                callback(null);
                throw err;
            }
            else{
                if(rows.length > 0){
                    callback(rows[0].roomid);
                }
                else{
                    callback(null);
                }
            }
        });
    }


    /**
     * 检查房间是否存在
     * @param roomid 
     * @param callback 
     */
    static is_room_exist(roomid, callback: (data: ret&boolean) => void = nop){

        const sql = 'SELECT * FROM t_rooms WHERE id = "' + roomid + '"';
        this.query(sql, (err, rows: ret[], fields) => {
            if(err){
                callback(false);
                throw err;
            }
            else{
                callback(rows.length > 0);
            }
        });

    }


    static set_id_of_user(userId, roomId?, callback:(flag: boolean)=>void = nop){
        
        if(roomId != null){
            roomId = '"' + roomId + '"';
        }

        const sql = `UPDATE t_users SET roomid = ${roomId} WHERE userid = "${userId}"`;
        this.query(sql, (err, rows: any[], fields) => {
            if(err){
                callback(false);
                throw err;
            }
            else{
                callback(rows.length > 0);
            }
        });
    }


    static is_user_exist(account, callback: (data: ret | boolean) => void = nop){
        if(account == null){
            callback(false);
            return;
        }

        const sql = `SELECT userid FROM t_users WHERE account = "${account}"`;
        this.query(sql, (err, rows: any[], fields) => {
            if(err){
                throw err;
            }
            if(rows.length == 0){
                callback(false);
                return;
            }
            callback(true);
        });
    }


    static create_user(account, name, coins, gems, sex, headimg, callback:(a:boolean)=>void = nop){
        if(null == account || name == null || coins == null || gems == null){
            callback(false);
            return;
        }
        if(headimg){
            headimg = `"${headimg}"`;
        }
        else{
            headimg = 'null';
        }
        name = crypto.toBase64(name);
        let sql = `INSERT INTO t_users(account,name,coins,gems,sex,headimg) VALUES("{0}","{1}",{2},{3},{4},{5})`;
        sql = sql.format(account, name, coins, gems, sex, headimg);
        this.query(sql, (err, rows, fields) => {
            if(err){
                throw err;
            }
            
            callback(true);
        });
    }


    /**
     * 使用account在t_users表中查找到gems信息并返回
     * @param account 
     * @param callback 
     */
    static get_gems(account, callback: (data: ret) => void = nop){
        
        const sql = `SELECT gems FROM t_users WHERE account = "${account}"`;
        this.query(sql, (err, rows, fields) => {
            if(err){
                callback(null);
                throw err;
            }

            if(rows.length == 0){
                callback(null);
                return;
            }
            callback(rows[0]);
        });
    }


    static create_room(roomId, conf, ip, port, create_time, callback: (data) => void = nop){

        let sql = `INSERT INTO t_rooms(uuid,id,base_info,ip,port,create_time) VALUES('{0}','{1}','{2}','{3}',{4},{5})`;
        const uuid = Date.now() + roomId;
        const baseInfo = JSON.stringify(conf);
        sql = sql.format(uuid, roomId, baseInfo, ip, port, create_time);

        this.query(sql, (err, row, fields) => {
            if(err){
                callback(null);
                throw err;
            }
            else{
                callback(uuid);
            }
        });
    }

    static get_room_addr(roomId, callback: (...agrs) => void = nop){

        if(roomId == null){
            callback(false, null, null);
            return;
        }

        const sql = `SELECT ip,port FROM t_rooms WHERE id= "${roomId}"`;
        this.query(sql, (err, rows, fields) => {
            if(err){
                callback(false, null, null);
                throw err;
            }
            if(rows.length > 0){
                callback(true, rows[0].ip, rows[0].port);
            }
            else{
                callback(false, null, null);
            }
        });
    }
    

    static update_seat_info(roomId, seatIndex, userId, icon, name, callback: (...agrs) => void = nop){
        let sql = `UPDATE t_rooms SET user_id{0} = {1},user_icon{0} = "{2}",user_name{0} = "{3}" WHERE id = "{4}"`;
        name = crypto.toBase64(name);
        sql = sql.format(seatIndex, userId, icon, name, roomId);
        this.query(sql, (err, row, fields) => {
            if(err){
                callback(false);
                throw err;
            }
            else{
                callback(true);
            }
        });
    }


    static get_room_data(roomId, callback: (...agrs) => void = nop){
        if(roomId == null){
            callback(null);
            return;
        }

        const sql = `SELECT * FROM t_rooms WHERE id = "${roomId}"`;
        this.query(sql, (err, rows, fields) => {
            if(err){
                callback(null);
                throw err;
            }
            if(rows.length > 0){
                rows[0].user_name0 = crypto.fromBase64(rows[0].user_name0);
                rows[0].user_name1 = crypto.fromBase64(rows[0].user_name1);
                rows[0].user_name2 = crypto.fromBase64(rows[0].user_name2);
                rows[0].user_name3 = crypto.fromBase64(rows[0].user_name3);
                callback(rows[0]);
            }
            else{
                callback(null);
            }
        });
    }


    static set_room_id_of_user(userId, roomId, callback: (data)=>void = nop){

        if(roomId != null){
            roomId = `"${roomId}"`;
        }

        const sql = `UPDATE t_users SET roomid = ${roomId} WHERE userid = "${userId}"`;
        this.query(sql, (err, rows, fields) => {
            if(err){
                callback(false);
                throw err;
            }
            else{
                callback(rows.length > 0);
            }
        });
    }

    static  get_message(type, version?, callback: (data:ret) => void = nop){
        
        let sql = `SELECT * FROM t_message WHERE type = "${type}"`;
        if(version == 'null' || !version){
            version = null;
        }

        if(version){
            version = `"${version}"`;
            sql += ' AND version != ' + version;
        }
        console.log('1111111' + sql);
        this.query(sql, (err, rows, fields) => {
            if(err){
                callback(null);
                throw err;
            }
            else{
                if(rows.length > 0){
                    callback(rows[0]);
                }
                else{
                    callback(null);
                }
            }
        });
    }
}